////////////////////////////////////////////////
// DESCRIPTION:
//    Interface based development support
//
// Legal Notices:
//    Copyright (C) 2005, EmbeddedFusion
//    ALL RIGHTS RESERVED
//
//    This file, software, or program is supplied under the terms of a
//    license agreement and/or nondisclosure agreement with EmbeddedFusion
//    Consulting and may not be copied or disclosed except in accordance
//    with the terms of that agreement.  This file, software, or program
//    contains copyrighted material and/or trade secret information of
//    EmbeddedFusion, and must be treated as such. EmbeddedFusion reserves
//    all rights in this material, except as the license agreement or
//    nondisclosure agreement specifically indicate.
//
//    All rights reserved.  No part of this program or publication may be
//    reproduced, transmitted, transcribed, stored in a retrieval system
//    retrieval system, or translated into any language or computer
//    language, in any form or by any means, electronic, mechanical,
//    magnetic, optical, chemical, manual, or otherwise, without the prior
//    written permission of EmbeddedFusion.
//
// Disclaimer:
//    EmbeddedFusion makes no warranty of any kind regarding
//    this code.  This code is provided on an "As Is" basis and
//    EmbeddedFusion will not provide any support assistance,
//    installation, training or other services.
//    EmbeddedFusion does not provide any updates, enhancements
//    or extensions. EmbeddedFusion specifically disclaims any
//    warranty of merchantability, non-infringement, fitness for any
//    particular purpose, or any other warranty.
//
//    EmbeddedFusion disclaims all liability, including liability
//    for infringement of any proprietary rights, relating to use of the
//    code. No license, express or implied, by estoppel or otherwise,
//    to any intellectual property rights is granted herein.
//
//    EmbeddedFusion has no responsibility under warranty, indemnification
//    or otherwise, for the modification or customization of any EmbeddedFusion
//    software by EmbeddedFusion, customer, website user or any third party even
//    if such customization and/or modification is done using EmbeddedFusion tools,
//    training or methods documented by EmbeddedFusion.
//
#pragma once

#include <wtypes.h>
#include <basetyps.h> 

// warning C4250: 'MyObj' : inherits 'IGuidCastImpl::IGuidCastImpl::GuidCast' via dominance
// This is expected and desired behavior so no warnings for it. 
#pragma warning(disable: 4250)

// when building tests on the desktop use assert
#ifndef UNDER_CE
#include <assert.h>
#define ASSERT assert
#endif

// Calling convention for use in Interface methods
// this is especially important for an interface called from C code
// to prevent the compiler from generating code that expects the
// "this" pointer to be in a register (__thiscall)
//
#define ITF_CALL STDMETHODCALLTYPE 

// optimization to prevent creation of Vtables for pure abstract interfaces
#define ITF_NOVTABLE __declspec(novtable)

namespace FusionWare
{
    ///////////////////////////////////////////////////////////////////
    // Description:
    //    Framework for using interfaces based on a GUID that does not
    //    need the overhead of COM or RTTI. This allows use of interface
    //    based design patterns in a boot loader or OAL where the FULL
    //    OS and C++ runtimes are not available.
    //
    namespace Interfaces
    {
        // The NULL Guid value 
        extern const IID GUID_NULL;

        // Like COM IUnknown or RTTI + Ref Counting without the COM runtime overhead
        // or the compiler RTTI overhead, which includes excpetion handling, so
        // bootloader, OAL and driver code can use shared libraries implementing
        // interfaces based on IGuidCast. 
        //
        [uuid("36DFD12E-10D5-43da-8186-41FF1F270807")]
        class ITF_NOVTABLE IGuidCast
        {
        public:
            ///////////////////////////////////////////////////////
            // Description: 
            //    Retieves another interface if the underlying object
            //    supports it. 
            //
            // Input: 
            //    id - GUID of the interface to retrieve from the object
            //
            // Returns: 
            //    void* - the requested interface cast as void* or NULL if not
            //            found.
            //     
            // Remarks: 
            //    This method allows a caller to query an object for
            //    implementation of a different interface it might
            //    support. AddRef() is called on the interface returned
            //    so it is the responsibility of the caller to make
            //    sure that Release is called when the interface is no
            //    longer needed. This is usually easiest using one of the
            //    smart pointer types InterfacePtr<> or GuidCastInterfacePtr<>
            //
            virtual bool ITF_CALL GuidCast(const GUID& id, void** ppRetVal)=0;
            
            ///////////////////////////////////////////////////////
            // Description: 
            //     Increments the internal reference count for the
            //     object. 
            //
            // Returns: 
            //     DWORD - Implentation specific; should be ignored
            //             except for debugging
            //     
            // Remarks: 
            //     The return value is usually the new count value;
            //     however this should not be relied upon for any
            //     use other than debugging. It could be any
            //     implementation specific value.
            //
            virtual DWORD ITF_CALL AddRef()=0;

            ///////////////////////////////////////////////////////
            // Description: 
            //     Decrements the internal reference count for the
            //     object. 
            //
            // Returns: 
            //     DWORD - Implentation specific; should be ignored
            //             except for debugging
            //     
            // Remarks: 
            //     The return value is usually the new count value;
            //     however this should not be relied upon for any
            //     use other than debugging. It could be any
            //     implementation specific value.
            //
            //     If the reference count reaches 0 this method will
            //     delete the underlying object.
            //     
            //     The interaface pointer used to make this call is no
            //     longer valid under ANY circumstances and must not be
            //     used.
            //
            virtual DWORD ITF_CALL Release()=0;
        };
        
        class IGuidCastImpl : virtual public IGuidCast
        {
        public:
            IGuidCastImpl() 
                : RefCount(0)
            {
            }

            virtual ~IGuidCastImpl();

        // Group = IGuidCast
        public:            
            virtual ULONG ITF_CALL AddRef();
            virtual ULONG ITF_CALL Release();                                                         
            // implemented in derived classes via interface map macros
            //virtual bool ITF_CALL GuidCast(const GUID& iid, void** ppRetVal);
            
        protected:
            long RefCount;
        };
        
      
        ///////////////////////////////////////////////////////
        // Description: 
        //     Declares and defines an interface map for an object
        //     only valid in the class declaration
        //
        // Input: 
        //    x - Class that implements the interfaces
        //
        // Remarks: 
        //    This macros is used in the public section of a 
        //    class declaration of a class that implements
        //    interfaces. It simplifies the process of 
        //    implementing IGuidCast::GuidCast(). The table
        //    created from the interface map macros is used
        //    by GuidCastHelper() to look up the interface
        //    in the table for the class and handle chaining
        //    to an interface map in a base class.
        // 
        #define BEGIN_INTERFACE_MAP(x)\
            typedef x __ItfMapClass;\
            virtual bool ITF_CALL GuidCast(const GUID& iid, void** ppRetVal) { \
            ASSERT(ppRetVal!=NULL);\
            *ppRetVal = NULL;

        ///////////////////////////////////////////////////////
        // Description: 
        //     Map entry for an interface
        //
        // Input: 
        //     i - Interface to add a map entry for
        //
        // Remarks: 
        //     The interface i must have a uuid associated with
        //     it either using the [uuid()] attributed syntax or
        //     the __declspec(uuid()) modifier
        //
        #define INTERFACE_MAP_ENTRY(i) \
        if(__uuidof(i) == iid) { i* pTemp = static_cast<i*>(this); pTemp->AddRef(); *ppRetVal=pTemp; return true; }\
        
        ///////////////////////////////////////////////////////
        // Description: 
        // 
        // Input: 
        //     i - Interface to add a map entry for
        //     T - interface class that derives from i
        // 
        // Remarks: 
        //     The interface i must have a uuid associated with
        //     it either using the [uuid()] attributed syntax or
        //     the __declspec(uuid()) modifier
        //     This creates an entry that allows for standard
        //     partial implementations of interfaces.
        //
        #define INTERFACE_MAP_ENTRY2(i,T)  \
    	if(__uuidof(i) == iid) { i* pTemp = static_cast<T*>(this); pTemp->AddRef(); *ppRetVal=pTemp; return true; }\

        ///////////////////////////////////////////////////////
        // Description: 
        //    Adds an entry to the interface map that chains
        //    to a parent class's interface map.
        //
        // Input: 
        //    classname - name of base class to chain to
        //
        // Remarks: 
        //    Chaining interface maps allows a derived class to
        //    add interfaces to what a parent class implements 
        //    and include both interface maps in the search 
        //    for an interface implementation in IGuidCast::GuidCast()
        //
        #define INTERFACE_MAP_CHAIN(classname) \
        if(classname::GuidCast(iid, ppRetVal)) return true; 
        
        /////////////////////////////////////////////////////////////////////////////////////////////
        // Description:
        //    Terminates the interface map
        //
        // Remarks:
        //    To use this map - the class it is applied to MUST be derived from an interface that is
        //    derived from IGuidCast. You must also initialize the RefCount member that this macro
        //    adds to the class to 0. 
        //
        #define END_INTERFACE_MAP \
        return false; }
         
        ///////////////////////////////////////////////////////////
        // Description:
        //     Template function to perform Guid casts
        //
        // Input:
        //     pFromType - pointer to an IGuidCast Derived interface
        //
        // Remarks:
        //     ToType should be an interface pointer and should have a
        //     UUID assigned to it. This function works like the built-in
        //     dynamic_cast<> but doesn' have the RTTI and exception 
        //     handling overhead.
        //
        template<class ToType> inline ToType guid_cast(IGuidCast* pFromType)
        {
            ToType pRetVal = NULL;
            if(pFromType!=NULL)
                (ToType)pFromType->GuidCast(__uuidof(ToType), (void**)&pRetVal);
                
            return pRetVal;    
        }
        
        // 
        // Wrapper class for use in -> operator of smart pointers.
        // This class prevents users of smart pointers from calling
        // Addref/Release on the contained pointer as that would
        // mess up the count.
        //
        template <class Itf>
        class NoAddRefReleaseInterface : public Itf
        {
        // hide parent class methods to prevent calling
        // them on the interface.
	    private:
		    ULONG ITF_CALL AddRef()=0;
		    ULONG ITF_CALL Release()=0;
        };

        // Smart pointer template for interface classes.
        template <class Itf>
        class InterfacePtr
        {
        public:
	        __forceinline InterfacePtr() { p=NULL; }

	        __forceinline InterfacePtr(Itf* pItf)
	        {
		        if ((p = pItf) != NULL)
			        p->AddRef();
	        }

	        __forceinline InterfacePtr(const InterfacePtr<Itf>& pItf)
	        {
		        if((p = pItf.p) != NULL)
			        p->AddRef();
	        }

	        __forceinline ~InterfacePtr()
	        {
		        if(p)
			        p->Release();
	        }

	        __forceinline void Release()
	        {
		        IGuidCast* pTemp = p;
		        if (pTemp)
		        {
			        p = NULL;
			        pTemp->Release();
		        }
	        }

	        __forceinline operator Itf*() const
	        {
		        return (Itf*)p;
	        }

	        __forceinline Itf& operator*() const
	        {
		        ASSERT(p!=NULL);
		        return *p; 
	        }

	        __forceinline Itf** operator&()
	        {
		        ASSERT(p==NULL);
		        return &p; 
	        }

	        __forceinline NoAddRefReleaseInterface<Itf>* operator->() const
	        {
		        ASSERT(p!=NULL);
		        return (NoAddRefReleaseInterface<Itf>*)p;
	        }

	        __forceinline Itf* operator=(Itf* pItf)
	        {
	            if(pItf != NULL)
		            pItf->AddRef();

	            if(p!=NULL)
		            p->Release();

	            p = pItf;
	            return p;
	        }

	        __forceinline Itf* operator=(const InterfacePtr<Itf>& pItf)
	        {
		        return operator=(pItf.p);
	        }

	        __forceinline bool operator!() const
	        {
		        return (p == NULL);
	        }

	        __forceinline bool operator<(Itf* pT) const
	        {
		        return p < pT;
	        }

	        __forceinline bool operator==(Itf* pT) const
	        {
		        return p == pT;
	        }

	        __forceinline void Attach(Itf* p2)
	        {
		        if(p)
			        p->Release();

		        p = p2;
	        }

	        __forceinline Itf* Detach()
	        {
		        Itf* pt = p;
		        p = NULL;
		        return pt;
	        }

	        template <class QItf>
	        __forceinline void GuidCast(QItf** pp) const
	        {
		        ASSERT(pp != NULL && *pp == NULL);
		        *pp = p->GuidCast(__uuidof(Q));
	        }

	        Itf* p;
        };
      
        // smart pointer template that includes automatic guid casting
        // to the interface type controlled by the smart pointer.
        template <class Itf, const GUID& iid = __uuidof(Itf)>
        class GuidCastInterfacePtr
        {
        public:
	        __forceinline GuidCastInterfacePtr() { p=NULL; }

	        __forceinline GuidCastInterfacePtr(Itf* pItf)
	        {
		        if ((p = pItf) != NULL)
			        p->AddRef();
	        }

	        __forceinline GuidCastInterfacePtr(const GuidCastInterfacePtr<Itf,iid>& pItf)
	        {
		        if ((p = pItf.p) != NULL)
			        p->AddRef();
	        }

	        __forceinline GuidCastInterfacePtr(IGuidCast* pItf)
	        {
		        p=NULL;
		        if(pItf != NULL)
			        p = guid_cast<Itf*>(pItf);
	        }

	        __forceinline ~GuidCastInterfacePtr()
	        {
		        if(p)
			        p->Release();
	        }

	        __forceinline void Release()
	        {
		        IGuidCast* pTemp = p;
		        if (pTemp)
		        {
			        p = NULL;
			        pTemp->Release();
		        }
	        }

	        __forceinline operator Itf*() const
	        {
		        return p;
	        }

	        __forceinline Itf& operator*() const
	        {
		        ASSERT(p!=NULL); return *p;
	        }

	        __forceinline Itf** operator&()
	        {
		        ASSERT(p==NULL);
		        return &p;
	        }

	        __forceinline NoAddRefReleaseInterface<Itf>* operator->() const
	        {
		        ASSERT(p!=NULL);
		        return (NoAddRefReleaseInterface<Itf>*)p;
	        }

	        __forceinline Itf* operator=(Itf* pItf)
	        {
	            if(pItf != NULL)
		            pItf->AddRef();

	            if(p!=NULL)
		            p->Release();

	            p = pItf;
	            return p;
	        }

	        __forceinline Itf* operator=(const InterfacePtr<Itf>& pItf)
	        {
		        return operator=(pItf.p);
	        }

	        __forceinline Itf* operator=(IGuidCast* pGC)
	        {
	            IGuidCast* pTemp = p;
	            p = NULL;
	            if (pGC != NULL)
		            p = guid_cast<Itf*>(pGC);

	            if (pTemp)
		            pTemp->Release();

	            return p;
	        }

	        __forceinline bool operator!() const
	        {
		        return (p == NULL);
	        }

	        __forceinline bool operator<(Itf* pItf) const
	        {
		        return p < pItf;
	        }

	        __forceinline bool operator==(Itf* pItf) const
	        {
		        return p == pItf;
	        }

	        __forceinline void Attach(Itf* p2)
	        {
		        if (p)
			        p->Release();
		        p = p2;
	        }

	        __forceinline Itf* Detach()
	        {
		        T* pt = p;
		        p = NULL;
		        return pt;
	        }

	        template <class QItf>
	        __forceinline void QueryInterface(QItf** ppItf)
	        {
		        ASSERT(pp != NULL && *pp == NULL);
		        *ppItf = guid_cast<QItf*>(p);
	        }
	        Itf* p;
        };
        
        // Declares the smart pointer typedefs for an interface.
        // This macro declares both a normal interface pointer and a 
        // GuidCast Version. Types are named with the Interface name
        // and Ptr or GCPtr appended to the end.
        // Example:
        //     DECLARE_INTERFACE_PTR(IFooBar)
		//
        //     is Equivalent to:
        //     typedef FusionWare::Interfaces::InterfacePtr<IFooBar> IFooBarPtr;
        //     typedef FusionWare::Interfaces::GuidCastInterfacePtr<IFooBar> IFooBarGCPtr;
        //      
        #define DECLARE_INTERFACE_PTR(Itf)\
            typedef FusionWare::Interfaces::InterfacePtr<Itf> Itf##Ptr; \
            typedef FusionWare::Interfaces::GuidCastInterfacePtr<Itf> Itf##GCPtr;
    }
}
